package com.gzc.just.play.last.war.sceneserver.battle.manager;

import com.gzc.just.play.last.war.common.handler.BattleSession;
import com.gzc.just.play.last.war.sceneserver.battle.model.BattleInfo;
import com.gzc.just.play.last.war.sceneserver.battle.model.BattleUserInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 增强的战斗会话管理器
 * 使用虚拟线程为每个战斗创建独立的BattleSession
 * 对应C++的SSBattleMgr
 */
@Component
public class EnhancedBattleSessionManager {
    
    private static final Logger log = LoggerFactory.getLogger(EnhancedBattleSessionManager.class);
    
    /** 战斗ID生成器 */
    private static final AtomicLong battleIdGenerator = new AtomicLong(1000);
    
    /** 战斗ID到BattleSession的映射 */
    private final ConcurrentHashMap<Long, BattleSession> battleSessions = new ConcurrentHashMap<>();
    
    /** 战斗ID到BattleInfo的映射 */
    private final ConcurrentHashMap<Long, BattleInfo> battleInfos = new ConcurrentHashMap<>();
    
    /** 用户ID到战斗ID的映射 */
    private final ConcurrentHashMap<Long, Long> userToBattle = new ConcurrentHashMap<>();
    
    /** 等待中的战斗队列 */
    private final Queue<BattleInfo> waitingBattles = new LinkedList<>();
    
    // ==================== 心跳相关 ====================
    /** 最后心跳时间 */
    private long lastHeartbeatTime = System.currentTimeMillis();
    
    /**
     * 创建新的战斗会话
     */
    public BattleInfo createBattle(BattleInfo.BattleType battleType, 
                                    Integer mapId, 
                                    Integer maxPlayers) {
        // 生成战斗ID
        long battleId = battleIdGenerator.incrementAndGet();
        
        // 创建BattleInfo
        BattleInfo battle = new BattleInfo();
        battle.setBattleId(battleId);
        battle.setStatus(BattleInfo.BattleStatus.WAITING);
        battle.setBattleType(battleType);
        battle.setMapId(mapId);
        battle.setMaxPlayers(maxPlayers);
        battle.setStartTime(System.currentTimeMillis());
        battle.setHeartBeatTime(System.currentTimeMillis());
        
        // 创建BattleSession，为每个战斗分配独立的虚拟线程
        String battleName = String.format("Battle-%d-%s-%d", battleId, battleType, mapId);
        BattleSession battleSession = BattleSession.createBattle(battleName);
        battleSession.start();
        
        // 存储到映射表
        battleSessions.put(battleId, battleSession);
        battleInfos.put(battleId, battle);
        
        log.info("Created new battle session: battleId={}, type={}, mapId={}, thread={}", 
                battleId, battleType, mapId, battleSession.getProcessingThread().getName());
        
        return battle;
    }
    
    /**
     * 获取战斗会话
     */
    public BattleSession getBattleSession(Long battleId) {
        return battleSessions.get(battleId);
    }
    
    /**
     * 获取战斗信息
     */
    public BattleInfo getBattleInfo(Long battleId) {
        return battleInfos.get(battleId);
    }
    
    /**
     * 添加玩家到战斗
     */
    public boolean addPlayerToBattle(Long battleId, BattleUserInfo userInfo) {
        BattleInfo battle = getBattleInfo(battleId);
        BattleSession session = getBattleSession(battleId);
        
        if (battle == null || session == null) {
            log.warn("Battle or session does not exist: battleId={}", battleId);
            return false;
        }
        
        if (battle.isFull()) {
            log.warn("Battle is full: battleId={}", battleId);
            return false;
        }
        
        // 添加到BattleInfo
        battle.addBattleUser(userInfo);
        userToBattle.put(userInfo.getUserId(), battleId);
        
        // 添加到BattleSession
        session.addPlayer(userInfo.getUserId(), userInfo.getNickname());
        
        log.info("Player joined battle session: userId={}, battleId={}, playerCount={}, thread={}", 
                userInfo.getUserId(), battleId, battle.getPlayerCount(), session.getProcessingThread().getName());
        
        return true;
    }
    
    /**
     * 从战斗中移除玩家
     */
    public void removePlayerFromBattle(Long userId) {
        Long battleId = userToBattle.remove(userId);
        if (battleId == null) {
            return;
        }
        
        BattleInfo battle = getBattleInfo(battleId);
        BattleSession session = getBattleSession(battleId);
        
        if (battle != null) {
            battle.getBattleUsers().removeIf(u -> u.getUserId().equals(userId));
        }
        
        if (session != null) {
            session.removePlayer(userId);
        }
        
        // 检查是否需要结束战斗
        if (battle != null && battle.getBattleUsers().isEmpty()) {
            endBattle(battleId);
        }
        
        log.info("Player left battle session: userId={}, battleId={}, playerCount={}", 
                userId, battleId, battle != null ? battle.getPlayerCount() : 0);
    }
    
    /**
     * 获取用户的战斗会话
     */
    public BattleSession getUserBattleSession(Long userId) {
        Long battleId = userToBattle.get(userId);
        return battleId != null ? getBattleSession(battleId) : null;
    }
    
    /**
     * 获取用户的战斗信息
     */
    public BattleInfo getUserBattleInfo(Long userId) {
        Long battleId = userToBattle.get(userId);
        return battleId != null ? getBattleInfo(battleId) : null;
    }
    
    /**
     * 开始战斗
     */
    public boolean startBattle(Long battleId) {
        BattleInfo battle = getBattleInfo(battleId);
        BattleSession session = getBattleSession(battleId);
        
        if (battle == null || session == null) {
            return false;
        }
        
        if (battle.getStatus() != BattleInfo.BattleStatus.WAITING) {
            log.warn("Incorrect battle status: battleId={}, status={}", 
                    battleId, battle.getStatus());
            return false;
        }
        
        // 更新BattleInfo状态
        battle.setStatus(BattleInfo.BattleStatus.IN_PROGRESS);
        battle.setStartTime(System.currentTimeMillis());
        
        // 启动BattleSession战斗循环
        session.startBattle();
        
        log.info("Battle started: battleId={}, playerCount={}, thread={}", 
                battleId, battle.getPlayerCount(), session.getProcessingThread().getName());
        
        return true;
    }
    
    /**
     * 结束战斗
     */
    public void endBattle(Long battleId) {
        BattleInfo battle = getBattleInfo(battleId);
        BattleSession session = getBattleSession(battleId);
        
        if (battle == null && session == null) {
            return;
        }
        
        // 更新BattleInfo状态
        if (battle != null) {
            battle.setStatus(BattleInfo.BattleStatus.FINISHED);
            battle.setEndTime(System.currentTimeMillis());
            battle.setDuration(battle.getEndTime() - battle.getStartTime());
            
            // 移除所有玩家
            List<Long> playerIds = new ArrayList<>();
            for (BattleUserInfo user : battle.getBattleUsers()) {
                playerIds.add(user.getUserId());
            }
            playerIds.forEach(this::removePlayerFromBattle);
        }
        
        // 停止BattleSession
        if (session != null) {
            session.stop();
        }
        
        // 移除映射
        battleInfos.remove(battleId);
        battleSessions.remove(battleId);
        
        log.info("Battle ended: battleId={}, duration={}ms", 
                battleId, battle != null ? battle.getDuration() : 0);
    }
    
    /**
     * 提交战斗消息到对应的战斗会话
     */
    public boolean submitBattleMessage(Long battleId, Long userId, Integer messageId, byte[] messageBytes) {
        BattleSession session = getBattleSession(battleId);
        if (session == null) {
            log.warn("Battle session does not exist: battleId={}", battleId);
            return false;
        }
        
        // 验证用户是否在此战斗中
        if (!userToBattle.getOrDefault(userId, -1L).equals(battleId)) {
            log.warn("User {} is not in battle {}", userId, battleId);
            return false;
        }
        
        return session.submitMessage(userId, messageId, messageBytes);
    }
    
    /**
     * 获取活跃战斗数量
     */
    public int getActiveBattleCount() {
        return (int) battleInfos.values().stream()
                .filter(b -> b.getStatus() == BattleInfo.BattleStatus.IN_PROGRESS)
                .count();
    }
    
    /**
     * 获取总战斗数量
     */
    public int getTotalBattleCount() {
        return battleInfos.size();
    }
    
    /**
     * 处理心跳
     */
    public void onHeartbeat() {
        long currentTime = System.currentTimeMillis();
        this.lastHeartbeatTime = currentTime;
        
        // 更新每个战斗的心跳时间
        for (BattleInfo battle : battleInfos.values()) {
            battle.setHeartBeatTime(currentTime);
        }
        
        // 检查超时战斗
        checkTimeoutBattles();
    }
    
    /**
     * 检查超时战斗
     */
    private void checkTimeoutBattles() {
        long currentTime = System.currentTimeMillis();
        long timeoutThreshold = 5 * 60 * 1000; // 5 minutes
        
        List<Long> timeoutBattles = new ArrayList<>();
        
        for (BattleInfo battle : battleInfos.values()) {
            if (battle.getStatus() == BattleInfo.BattleStatus.WAITING) {
                if (currentTime - battle.getStartTime() > timeoutThreshold) {
                    timeoutBattles.add(battle.getBattleId());
                }
            }
        }
        
        for (Long battleId : timeoutBattles) {
            log.warn("Battle timeout, auto-end: battleId={}", battleId);
            endBattle(battleId);
        }
    }
    
    /**
     * 获取所有活跃战斗列表
     */
    public List<BattleInfo> getActiveBattles() {
        return new ArrayList<>(battleInfos.values());
    }
    
    /**
     * 获取玩家的战斗信息
     */
    public BattleUserInfo getPlayerBattleInfo(Long userId) {
        BattleInfo battle = getUserBattleInfo(userId);
        if (battle == null) {
            return null;
        }
        
        for (BattleUserInfo user : battle.getBattleUsers()) {
            if (user.getUserId().equals(userId)) {
                return user;
            }
        }
        
        return null;
    }
    
    /**
     * 更新玩家战斗信息
     */
    public void updatePlayerBattleInfo(Long userId, BattleUserInfo userInfo) {
        BattleInfo battle = getUserBattleInfo(userId);
        if (battle != null) {
            for (int i = 0; i < battle.getBattleUsers().size(); i++) {
                if (battle.getBattleUsers().get(i).getUserId().equals(userId)) {
                    battle.getBattleUsers().set(i, userInfo);
                    break;
                }
            }
        }
    }
    
    /**
     * 清除所有战斗数据（仅用于测试或关闭）
     */
    public void clearAllBattles() {
        // 停止所有战斗会话
        for (BattleSession session : battleSessions.values()) {
            try {
                session.stop();
            } catch (Exception e) {
                log.error("Error stopping battle session", e);
            }
        }
        
        // 清除所有映射
        battleSessions.clear();
        battleInfos.clear();
        userToBattle.clear();
        
        log.info("Cleared all battle data and sessions");
    }
    
    /**
     * 获取性能统计
     */
    public Map<String, Object> getPerformanceStats() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalBattles", getTotalBattleCount());
        stats.put("activeBattles", getActiveBattleCount());
        stats.put("totalPlayers", userToBattle.size());
        
        // 计算每个战斗的总队列大小
        int totalQueueSize = 0;
        for (BattleSession session : battleSessions.values()) {
            totalQueueSize += session.getQueueSize();
        }
        stats.put("totalQueueSize", totalQueueSize);
        
        return stats;
    }
}